Windy City Weapon Stats
\n `).join('');
}
// Drug data for drug randomizer
// Build drug pools straight from the DRUGS array used by the Drugs section
const ALL_DRUGS = (Array.isArray(window.DRUGS) ? window.DRUGS : []).map(d => ({
name: d.name,
src: d.src,
tier: d.tier || 't1'
}));
// Until tiers exist on DRUGS, treat both T1 and T2 as the full list so the randomizer always uses the Drugs section items.
const t1Drugs = ALL_DRUGS;
const t2Drugs = ALL_DRUGS;
function getDrugPool() {
const select = document.getElementById('drug-randomize-tier-select');
const chosen = select ? select.value : 'Any';
if (chosen === 'Tier 1') return t1Drugs;
if (chosen === 'Tier 2') return t2Drugs;
return ALL_DRUGS;
}
function spinDrugs() {
const tier = document.getElementById('drug-randomize-tier-select')?.value || 't1';
// Build from the rendered Drugs grid: pull the actual drug name from the badge
const cards = Array.from(document.querySelectorAll('#drugs .drug-grid .drug-card'));
let all = cards.map(c => {
const badge = c.querySelector('.drug-badge'); // drug name
const name = (badge?.textContent || '').trim();
const img = c.querySelector('img')?.src || '';
return { name, src: img };
}).filter(d => d.name);
// De‑dupe by name (pool, not results)
const seen = new Set();
all = all.filter(d => (seen.has(d.name) ? false : (seen.add(d.name), true)));
// Fallback to DRUGS array if grid hasn't rendered yet
if (!all.length && Array.isArray(window.DRUGS)) {
all = window.DRUGS.filter(d => d && d.name).map(d => ({ name: d.name, src: d.src || '' }));
}
// Optional tier filtering if items have a 'tier' ('t1'/'t2')
let pool = all;
if (all.length && typeof all[0] === 'object' && 'tier' in all[0]) {
if (tier === 't2') {
pool = all.filter(d => String(d.tier).toLowerCase() === 't2');
} else {
pool = all.filter(d => String(d.tier).toLowerCase() === 't1' || !d.tier);
}
if (!pool.length) pool = all;
}
// Keep your original spin counts
let count = (tier === 't2')
? Math.floor(Math.random() * 81) + 100 // 100–180
: Math.floor(Math.random() * 26) + 75; // 75–100
// Spin and aggregate counts per drug
const counts = Object.create(null);
for (let i = 0; i < count; i++) {
const idx = Math.floor(Math.random() * pool.length);
const name = pool[idx]?.name || 'Unknown';
counts[name] = (counts[name] || 0) + 1;
}
// Render as "Name xN" lines, sorted by highest quantity first
const out = document.getElementById('drug-spin-result');
if (out) {
const rows = Object.entries(counts)
.sort((a,b) => b[1] - a[1])
.map(([name, qty]) => `
${name} x${qty}`)
.join('');
out.innerHTML = '
';
}
}
function closeLightbox(){
document.getElementById('lightbox').classList.add('hidden');
}
document.addEventListener('click', function(e){
if(e.target && e.target.id === 'lightbox-close') closeLightbox();
if(e.target && e.target.classList && e.target.classList.contains('lightbox-backdrop')) closeLightbox();
});
document.addEventListener('keydown', function(e){
if(e.key === 'Escape') closeLightbox();
});
function wireLightbox(){
// grid cards
document.querySelectorAll('#tier1 .weapon-grid .weapon').forEach(card => {
const img = card.querySelector('img');
const name = (card.querySelector('.name-badge')?.textContent || img?.alt || '').trim();
if(img){
img.style.cursor = 'zoom-in';
img.addEventListener('click', (ev)=>{ ev.stopPropagation(); openLightbox(img.src, name); });
}
});
// randomizer results
document.querySelectorAll('#spin-result .weapon').forEach(card => {
const img = card.querySelector('img');
const name = (card.querySelector('.stats strong')?.textContent || img?.alt || '').trim();
if(img){
img.style.cursor = 'zoom-in';
img.addEventListener('click', (ev)=>{ ev.stopPropagation(); openLightbox(img.src, name); });
}
});
}
document.addEventListener('DOMContentLoaded', wireLightbox);
// ---- CS:GO style reel spin ----
function buildPool(tier){
const pool = [];
if(tier === 'tier2' && (typeof t2Weapons !== 'undefined') && t2Weapons.length){
// weight slightly, but if empty fallback to t1
const wt = t2Weapons.length < 5 ? 3 : 2;
t2Weapons.forEach(w=>{ for(let i=0;i
{ for(let i=0;i<3;i++) pool.push({...w}); });
}
return pool;
}
function casePool(tier){
const raw = casePool_raw(tier);
return weightedPoolFrom(raw);
}
function pickRandom(pool){ return pool[Math.floor(Math.random()*pool.length)]; }
// ---- Multi-reel CS:GO style spins ----
function computeReelCount(tier){
if(tier === 'test') return 2;
if(tier === 'tier1') return 4;
if(tier === 'tier2') return 6; // change if you want
return 2;
}
function createReelEl(sizeClass){
const wrap = document.createElement('div');
wrap.className = 'csgo-wrap ' + (sizeClass || 'single');
wrap.innerHTML = `
`;
return wrap;
}
function poolForTier(tier){
const pool = [];
// If tier2 selected and we have any t2 items, include them weighted higher
if(tier === 'tier2' && typeof t2Weapons !== 'undefined' && t2Weapons.length){
t2Weapons.forEach(w=>{ for(let i=0;i<3;i++) pool.push({...w}); });
}
// Always include T1 pool as base so "any weapons" can appear
if(typeof t1Weapons !== 'undefined' && t1Weapons.length){
t1Weapons.forEach(w=>{ for(let i=0;i<2;i++) pool.push({...w}); });
}
return pool;
}
function casePool(tier){
const raw = casePool_raw(tier);
return weightedPoolFrom(raw);
}
function pick(pool){ return pool[Math.floor(Math.random()*pool.length)]; }
async function spinCSGO(){
const tier = document.getElementById('randomize-tier-select').value;
const reelsWrap = document.getElementById('csgo-container');
const winnersWrap = document.getElementById('csgo-winners');
if(!reelsWrap) return;
reelsWrap.querySelectorAll('.csgo-wrap').forEach(e=>e.remove());
winnersWrap.innerHTML = '';
const count = computeReelCount(tier);
const pool = poolForTier(tier);
const avoidDupes = true;
if(!pool.length){ winnersWrap.textContent = 'No items available.'; return; }
const reels = [];
for(let i=0;i= 4 ? 'small' : 'single');
const reel = reelEl.querySelector('.csgo-reel');
reelsWrap.prepend(reelEl); // add before winners div
reels.push({wrap: reelEl, reel, chosen: null});
}
const tiles = 100;
const cardW = 102;
const durationBase = 2600;
reels.forEach((r, idx)=>{
// Build tiles
r.reel.innerHTML = '';
let chosenIdx = Math.floor(tiles*0.7 + Math.random()*20);
let chosenW = null;
for(let i=0;i0? chosenW?.name : null), avoidDupes);
if(i === chosenIdx) chosenW = w;
const card = document.createElement('div');
card.className = 'csgo-card ' + (w.tier && w.tier.startsWith('Tier 2') ? 't2':'t1');
const img = document.createElement('img');
img.src = w.img || '';
img.alt = w.name || '';
img.style.cursor = 'zoom-in';
img.addEventListener('click', (ev)=>{ ev.stopPropagation(); openLightbox(img.src, w.name); });
const nm = document.createElement('div');
nm.className = 'name';
nm.textContent = w.name || '';
card.appendChild(img);
card.appendChild(nm);
r.reel.appendChild(card);
}
r.chosen = {idx: chosenIdx, weapon: chosenW};
});
// Play ticks
const tick = document.getElementById('spin-sound');
let tickTimer = setInterval(()=>{ try{ tick.currentTime = 0; tick.play(); }catch(e){} }, 140);
// Animate each reel with slight stagger
const animPromises = reels.map((r, i)=> new Promise(resolve => {
const wrapRect = r.wrap.getBoundingClientRect();
const markerX = wrapRect.width/2;
const targetOffset = r.chosen.idx*cardW + cardW/2 - markerX;
const dur = durationBase + i*200 + Math.floor(Math.random()*300);
r.reel.classList.add('spinning');
r.reel.style.transition = 'none';
r.reel.style.transform = 'translateX(0px)';
void r.reel.offsetWidth;
r.reel.style.transition = `transform ${dur}ms cubic-bezier(0.08, 0.7, 0.12, 1)`;
r.reel.style.transform = `translateX(-${targetOffset}px)`;
setTimeout(()=>{
r.reel.classList.remove('spinning');
resolve();
}, dur + 30);
}));
await Promise.all(animPromises);
clearInterval(tickTimer);
// Show winners as cards; clicking opens lightbox
reels.forEach(r=>{
const w = r.chosen.weapon;
const card = document.createElement('div');
card.className = 'csgo-win-card ' + (w.tier && w.tier.startsWith('Tier 2') ? 't2':'t1');
const img = document.createElement('img');
img.src = w.img || '';
img.alt = w.name || '';
img.addEventListener('click', ()=>openLightbox(img.src, w.name));
const nm = document.createElement('div');
nm.className = 'name';
nm.textContent = w.name || '';
card.appendChild(img);
card.appendChild(nm);
winnersWrap.appendChild(card);
});
}
// Re-bind Spin button
(function(){
const spinBtn = Array.from(document.querySelectorAll('button')).find(b=>b.textContent.trim().toLowerCase()==='spin');
if(spinBtn){ spinBtn.removeAttribute('onclick'); spinBtn.addEventListener('click', spinCSGO); }
})();
// ---- Spotlight Reveal Randomizer ----
function poolForTier(tier){
const pool = [];
if(tier === 'tier2' && typeof t2Weapons !== 'undefined' && t2Weapons.length){
t2Weapons.forEach(w=>{ for(let i=0;i<3;i++) pool.push({...w}); });
}
if(typeof t1Weapons !== 'undefined' && t1Weapons.length){
t1Weapons.forEach(w=>{ for(let i=0;i<2;i++) pool.push({...w}); });
}
return pool;
}
function casePool(tier){
const raw = casePool_raw(tier);
return weightedPoolFrom(raw);
}
function computeCount(tier){
if(tier === 'test') return 2;
if(tier === 'tier1') return 4;
if(tier === 'tier2') return 6;
return 2;
}
function pick(pool){ return pool[Math.floor(Math.random()*pool.length)]; }
function openWinnerCard(w, winnersWrap){
const card = document.createElement('div');
card.className = 'win-card ' + (w.tier && w.tier.startsWith('Tier 2') ? 't2':'t1');
const img = document.createElement('img');
img.src = w.img || ''; img.alt = w.name || '';
img.addEventListener('click', ()=>openLightbox(img.src, w.name));
const nm = document.createElement('div'); nm.className='name'; nm.textContent = w.name || '';
card.appendChild(img); card.appendChild(nm);
winnersWrap.appendChild(card);
}
async function spinSpotlight(){
const tier = document.getElementById('randomize-tier-select')?.value || 'tier1';
const stageCard = document.getElementById('spotlight-card');
const imgEl = document.getElementById('spotlight-img');
const nameEl = document.getElementById('spotlight-name');
const winnersWrap = document.getElementById('spotlight-winners');
winnersWrap.innerHTML = '';
const pool = poolForTier(tier);
if(!pool.length){ winnersWrap.textContent = 'No items available.'; return; }
const count = computeCount(tier);
// optional: prevent duplicate immediate repeats
let lastName = null;
for(let i=0;isetTimeout(r, 900)); // reveal time
openWinnerCard(w, winnersWrap);
await new Promise(r=>setTimeout(r, 280)); // small pause between reveals
}
}
// Bind Spin button to spotlight
(function(){
const spinBtn = Array.from(document.querySelectorAll('button')).find(b=>b.textContent.trim().toLowerCase()==='spin');
if(spinBtn){ spinBtn.removeAttribute('onclick'); spinBtn.addEventListener('click', spinSpotlight); }
})();
// -------- One-by-one compact case spinner --------
function casePool_raw(tier){
const pool = [];
if(tier === 'refill' && typeof t1Weapons !== 'undefined' && t1Weapons.length){
// Refill: only t1 weapons
t1Weapons.forEach(w=>{ pool.push({...w}); });
} else {
if(tier === 'tier2' && typeof t2Weapons !== 'undefined' && t2Weapons.length){
t2Weapons.forEach(w=>{ for(let i=0;i<3;i++) pool.push({...w}); });
}
if(typeof t1Weapons !== 'undefined' && t1Weapons.length){
t1Weapons.forEach(w=>{ for(let i=0;i<2;i++) pool.push({...w}); });
}
}
return pool;
}
function casePool(tier){
const raw = casePool_raw(tier);
return weightedPoolFrom(raw);
}
function caseCount(tier){
if(tier === 'test') return 2;
if(tier === 'tier1') return 4;
if(tier === 'tier2') return 6;
if(tier === 'refill') return 1;
return 2;
}
function pick(pool){ return pool[Math.floor(Math.random()*pool.length)]; }
function openWinCard(w){
const winners = document.getElementById('case-winners');
const card = document.createElement('div');
card.className = 'win-card ' + (w.tier && w.tier.startsWith('Tier 2') ? 't2':'t1');
const img = document.createElement('img');
img.src = w.img || ''; img.alt = w.name || '';
img.addEventListener('click', ()=>openLightbox(img.src, w.name));
const nm = document.createElement('div'); nm.className='name'; nm.textContent = w.name || '';
card.appendChild(img); card.appendChild(nm); winners.appendChild(card);
}
// REPLACED with accurate version
function buildReel_old(pool){
const reel = document.getElementById('case-reel');
reel.innerHTML = '';
const tiles = 90;
let chosenIdx = Math.floor(tiles*0.65 + Math.random()*14);
let chosen = null;
for(let i=0;isetTimeout(r, ms+40));
}
async function spinCaseOneByOne(){
const tier = document.getElementById('randomize-tier-select').value;
const winners = document.getElementById('case-winners'); winners.innerHTML='';
const pool = casePool(tier);
if(!pool.length){ winners.textContent='No items available.'; return; }
const count = caseCount(tier);
let lastName = null;
for(let i=0;i{ try{ snd.currentTime=0; snd.play(); }catch(e){} }, 120);
await animateReelAccurate(reel, items, chosenIdx, ms);
clearInterval(tickTimer);
let w = chosen || pick(pool);
// If duplicate and we're NOT allowing it this time, nudge to nearest different card
if(lastName && w.name===lastName && Math.random() > DUPLICATE_CHANCE){
// find nearest index with a different name
let bestIdx = null;
for(let delta=1; delta= 0 && items[left].w.name !== lastName){ bestIdx = left; break; }
}
if(bestIdx != null){
// micro-slide to that card so it matches the visual landing
const track = document.querySelector('.case-track');
const rect = track.getBoundingClientRect();
const el = items[bestIdx].el;
const target = el.offsetLeft + el.getBoundingClientRect().width/2 - rect.width/2;
reel.style.transition = `transform 380ms cubic-bezier(0.12, 0.7, 0.1, 1)`;
reel.style.transform = `translate3d(-${Math.max(0, target)}px,0,0)`;
await new Promise(r=>setTimeout(r, 400));
w = items[bestIdx].w;
}
}
lastName = w.name;
openWinCard(w);
await new Promise(r=>setTimeout(r, 160)); // tiny pause before next pick
}
}
// Bind Spin to this new flow
(function(){
const spinBtn = Array.from(document.querySelectorAll('button')).find(b=>b.textContent.trim().toLowerCase()==='spin');
if(spinBtn){ spinBtn.removeAttribute('onclick'); spinBtn.addEventListener('click', spinCaseOneByOne); }
})();
function buildReel(pool){
const reel = document.getElementById('case-reel');
reel.innerHTML = '';
const tiles = 90;
const items = [];
for(let i=0;isetTimeout(r, ms+40));
}
// ---- Rarity weighting + low-dup logic ----
// Edit this map to set each weapon's rarity: 'grey' | 'green' | 'blue' | 'purple'
// Defaults to 'grey' (common) if a name is not listed here.
const rarityMap = {
'Glock 19':'grey',
'Glock 17':'grey',
'Glock 17 Gen 5':'blue',
'Glock 19x':'grey',
'Sig P320':'grey',
'Walther p88':'grey',
'Olive g19x':'green',
'Olive glock 17':'grey',
'Glock 19 Foregrip':'grey',
'Hk45':'grey',
'Glock 45':'grey',
'Glock 23':'grey',
'Glock 43':'grey',
'Fn 57':'purple', // example: make rarer than grey
'Canik':'green', // example: uncommon
'G26':'green', // example: uncommon
'1911':'purple' // example: rarest
};
const rarityWeight = { grey: 6, green: 4, blue: 3, purple: 2 }; // higher = more common
function rarityOf(name){
const r = rarityMap[name];
return (r==='green'||r==='blue'||r==='purple') ? r : 'grey';
}
function weightedPoolFrom(list){
const out = [];
list.forEach(w=>{
const r = rarityOf(w.name);
const k = rarityWeight[r] || rarityWeight.grey;
for(let i=0;i ~15% chance.
const DUPLICATE_CHANCE = 0.22;
![Drug image]()